/*
 * Codegen for `traverse`.
 *
 * Parses Rust AST type definitions from files in `crates/oxc_ast/src/ast`, and generates:
 * - `src/traverse.rs`
 * - `src/ancestor.rs`
 * - `src/walk.rs`
 *
 * This is a quick-and-dirty version written in JS for speed of implementation.
 * We should do this properly with a Rust build script using `syn` etc.
 */

import { exec } from "child_process";
import { writeFile } from "fs/promises";
import { join as pathJoin } from "path";
import { fileURLToPath } from "url";
import { promisify } from "util";
import generateAncestorsCode from "./lib/ancestor.mjs";
import getTypesFromCode from "./lib/parse.mjs";
import generateTraverseTraitCode from "./lib/traverse.mjs";
import generateWalkFunctionsCode from "./lib/walk.mjs";

const execAsync = promisify(exec);

const PREAMBLE =
  "// Auto-generated code, DO NOT EDIT DIRECTLY!\n" +
  "// Generated by `oxc_traverse/scripts/build.mjs`.\n" +
  "// To alter this generated file you have to edit the codegen.\n\n";

const types = await getTypesFromCode();

const outputDirPath = pathJoin(fileURLToPath(import.meta.url), "../../src/generated");

await Promise.all([
  writeToFile("traverse.rs", generateTraverseTraitCode(types)),
  writeToFile("ancestor.rs", generateAncestorsCode(types)),
  writeToFile("walk.rs", generateWalkFunctionsCode(types)),
]);

/**
 * @param {string} filename
 * @param {string} code
 */
async function writeToFile(filename, code) {
  code = `${PREAMBLE}${code}`;
  const path = pathJoin(outputDirPath, filename);
  // oxlint-disable-next-line no-console
  console.log("Writing:", path);
  await writeFile(path, code);
  await execAsync(`rustfmt ${JSON.stringify(path)}`);
}
